class JournalActivity(JournalWindow): def __init__(self): logging.debug('STARTUP: Loading the journal') JournalWindow.__init__(self) self.set_title(_('Journal')) self._main_view = None self._project_view = None self._secondary_view = None self._list_view = None self._detail_view = None self._main_toolbox = None self._detail_toolbox = None self._volumes_toolbar = None self._mount_point = '/' self._active_view = JournalViews.MAIN self.project_metadata = None self._editing_mode = False self._setup_main_view() self._setup_secondary_view() self._setup_project_view() self.add_events(Gdk.EventMask.ALL_EVENTS_MASK) self._realized_sid = self.connect('realize', self.__realize_cb) self.connect('window-state-event', self.__window_state_event_cb) self.connect('key-press-event', self.__key_press_event_cb) self.connect('focus-in-event', self._focus_in_event_cb) self.connect('focus-out-event', self._focus_out_event_cb) model.created.connect(self.__model_created_cb) model.updated.connect(self.__model_updated_cb) model.deleted.connect(self.__model_deleted_cb) self._dbus_service = JournalActivityDBusService(self) self.iconify() self._critical_space_alert = None self._check_available_space() session.get_session_manager().shutdown_signal.connect( self._session_manager_shutdown_cb) def volume_error_cb(self, gobject, message, severity): alert = ErrorAlert(title=severity, msg=message) alert.connect('response', self.__alert_response_cb) self.add_alert(alert) alert.show() def __alert_response_cb(self, alert, response_id): self.remove_alert(alert) def __realize_cb(self, window): xid = window.get_window().get_xid() SugarExt.wm_set_bundle_id(xid, _BUNDLE_ID) activity_id = activityfactory.create_activity_id() SugarExt.wm_set_activity_id(xid, str(activity_id)) self.disconnect(self._realized_sid) self._realized_sid = None def _session_manager_shutdown_cb(self, event): self.destroy() def can_close(self): return False def list_view_signal_connect(self, list_view): list_view.connect('detail-clicked', self.__detail_clicked_cb) list_view.connect('clear-clicked', self.__clear_clicked_cb) list_view.connect('volume-error', self.volume_error_cb) list_view.connect('title-edit-started', self.__title_edit_started_cb) list_view.connect('title-edit-finished', self.__title_edit_finished_cb) list_view.connect('selection-changed', self.__selection_changed_cb) list_view.connect('project-view-activate', self.project_view_activated_cb) def _create_volumes_toolbar(self): self._volumes_toolbar = VolumesToolbar() self._volumes_toolbar.connect('volume-changed', self.__volume_changed_cb) self._volumes_toolbar.connect('volume-error', self.volume_error_cb) return self._volumes_toolbar def _setup_main_view(self): self._main_toolbox = MainToolbox() self._edit_toolbox = EditToolbox(self) self._main_view = Gtk.VBox() self._add_new_box = AddNewBar(_('Add new project')) self._add_new_box.activate.connect(self.__add_project_activate_cb) self._main_view.pack_start(self._add_new_box, False, True, style.DEFAULT_SPACING) self._main_view.set_can_focus(True) self._list_view = ListView(self, enable_multi_operations=True) self.list_view_signal_connect(self._list_view) tree_view = self._list_view.tree_view tree_view.connect('choose-project', self.__choose_project_cb) self._main_view.pack_start(self._list_view, True, True, 0) self._list_view.show_all() volumes_toolbar = self._create_volumes_toolbar() self._main_view.pack_start(volumes_toolbar, False, True, 0) self._main_toolbox.connect('query-changed', self._query_changed_cb) self._main_toolbox.search_entry.connect('icon-press', self.__search_icon_pressed_cb) self._main_toolbox.set_mount_point(self._mount_point) def _setup_project_view(self): self._project_view = ProjectView() project_vbox = self._project_view.get_vbox() add_new_box = AddNewBar() add_new_box.activate.connect(self.__add_new_activate_cb) add_new_box.show_all() project_vbox.pack_start(add_new_box, False, True, style.DEFAULT_SPACING / 3) self._entry_project = add_new_box.get_entry() self._list_view_project = self._project_view.create_list_view_project() self.list_view_signal_connect(self._list_view_project) project_vbox.pack_start(self._list_view_project, True, True, 0) self._list_view_project.show() def get_add_new_box(self): return self._add_new_box def get_list_view(self): return self._list_view def project_view_activated_cb(self, list_view, metadata): self.project_metadata = metadata self._project_view.set_project_metadata(self.project_metadata) self._project_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._active_view = JournalViews.PROJECT self.set_canvas(self._project_view) self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() query = {} query['project_id'] = self.project_metadata['uid'] self._list_view_project.update_with_query(query) self._project_view.show_all() def _setup_secondary_view(self): self._secondary_view = Gtk.VBox() self._detail_toolbox = DetailToolbox(self) self._detail_toolbox.connect('volume-error', self.volume_error_cb) self._detail_view = DetailView(self) self._detail_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._secondary_view.pack_end(self._detail_view, True, True, 0) self._detail_view.show() def __add_project_activate_cb(self, bar, title): initialize_journal_object(title=title, bundle_id=PROJECT_BUNDLE_ID, activity_id=None, project_metadata=None) def __add_new_activate_cb(self, bar, title): shell_model = shell.get_model() activity = shell_model.get_active_activity() if activity.has_shell_window(): return if shell.get_model().has_modal(): return chooser = ActivityChooser() activity.push_shell_window(chooser) chooser.connect('hide', activity.pop_shell_window) text = _("Choose an activity to start '%s' with") % title chooser.set_title(text) chooser.connect('activity-selected', self.__activity_selected_cb, title) chooser.show_all() def __activity_selected_cb(self, widget, bundle_id, activity_id, title): initialize_journal_object(title=title, bundle_id=bundle_id, activity_id=activity_id, project_metadata=self.project_metadata) def __key_press_event_cb(self, widget, event): #if not self._main_toolbox.search_entry.has_focus(): #self._main_toolbox.search_entry.grab_focus() keyname = Gdk.keyval_name(event.keyval) if keyname == 'Escape': self._main_toolbox.clear_query() self.show_main_view() def __choose_project_cb(self, tree_view, metadata_to_send): project_chooser = ObjectChooser(self.get_window()) project_chooser.show_all() project_chooser.connect('response', self.__project_chooser_response_cb, metadata_to_send) project_chooser._toolbar._proj_list_button_clicked_cb(None) def __project_chooser_response_cb(self, project_chooser, response_value, metadata_to_send): if response_value == Gtk.ResponseType.DELETE_EVENT: project_chooser.destroy() return object_id = project_chooser.get_selected_object_id() metadata = model.get(object_id) jobject_to_send = datastore.get(metadata_to_send['uid']) datastore.delete(metadata_to_send['uid']) jobject_to_send.metadata['project_id'] = metadata['uid'] datastore.write(jobject_to_send) project_chooser.destroy() def __detail_clicked_cb(self, list_view, object_id): metadata = model.get(object_id) activity = metadata.get('activity', None) if activity == PROJECT_BUNDLE_ID: self.project_view_activated_cb(list_view, metadata) else: self._show_secondary_view(object_id) def __clear_clicked_cb(self, list_view): self._main_toolbox.clear_query() def __selection_changed_cb(self, list_view, selected_items): self._editing_mode = selected_items != 0 self._edit_toolbox.set_selected_entries(selected_items) self._edit_toolbox.display_selected_entries_status() self.show_main_view() def update_selected_items_ui(self): selected_items = \ len(self.get_list_view().get_model().get_selected_items()) self.__selection_changed_cb(None, selected_items) def __go_back_clicked_cb(self, detail_view): self.show_main_view() def _query_changed_cb(self, toolbar, query): self._list_view.update_with_query(query) self.show_main_view() self._add_new_box.props.visible = \ query.get('activity') == PROJECT_BUNDLE_ID def __search_icon_pressed_cb(self, entry, icon_pos, event): self._main_view.grab_focus() def __title_edit_started_cb(self, list_view): self.disconnect_by_func(self.__key_press_event_cb) def __title_edit_finished_cb(self, list_view): self.connect('key-press-event', self.__key_press_event_cb) def show_main_view(self): self._active_view = JournalViews.MAIN self.project_metadata = None if self._editing_mode: self._toolbox = self._edit_toolbox self._toolbox.set_total_number_of_entries( self.get_total_number_of_entries()) else: self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() if self.canvas != self._main_view: self.set_canvas(self._main_view) self._main_view.show() def _show_secondary_view(self, object_id): self._active_view = JournalViews.DETAIL metadata = model.get(object_id) try: self._detail_toolbox.set_metadata(metadata) except Exception: logging.exception('Exception while displaying entry:') self.set_toolbar_box(self._detail_toolbox) self._detail_toolbox.show() try: self._detail_view.props.metadata = metadata except Exception: logging.exception('Exception while displaying entry:') self.set_canvas(self._secondary_view) self._secondary_view.show() def show_object(self, object_id): metadata = model.get(object_id) if metadata is None: return False else: self._show_secondary_view(object_id) return True def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug('Selected volume: %r.', mount_point) self._mount_point = mount_point self.set_editing_mode(False) self._main_toolbox.set_mount_point(mount_point) self._edit_toolbox.batch_copy_button.update_mount_point() def __model_created_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) self._main_toolbox.refresh_filters() self._check_available_space() def __model_updated_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self._detail_view.refresh() self._check_available_space() def __model_deleted_cb(self, sender, **kwargs): if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self.show_main_view() def _focus_in_event_cb(self, window, event): self._set_is_visible(True) def _focus_out_event_cb(self, window, event): self._set_is_visible(False) def __window_state_event_cb(self, window, event): logging.debug('window_state_event_cb %r', self) if event.changed_mask & Gdk.WindowState.ICONIFIED: state = event.new_window_state visible = not state & Gdk.WindowState.ICONIFIED self._set_is_visible(visible) def _set_is_visible(self, visible): if self._active_view == JournalViews.MAIN: self._list_view.set_is_visible(visible) elif self._active_view == JournalViews.PROJECT: self._list_view_project.set_is_visible(visible) def _check_available_space(self): """Check available space on device If the available space is below threshold an alert will be shown which suggests deleting old journal entries. """ if self._critical_space_alert: return stat = os.statvfs(env.get_profile_path()) free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] if free_space < (_SPACE_THRESHOLD * 1024 * 1024): self._critical_space_alert = ModalAlert() self._critical_space_alert.connect('destroy', self.__alert_closed_cb) self._critical_space_alert.show() def __alert_closed_cb(self, data): self.show_main_view() self.reveal() self._critical_space_alert = None def set_active_volume(self, mount): self._volumes_toolbar.set_active_volume(mount) def show_journal(self): """Become visible and show main view""" self.reveal() self.show_main_view() def get_total_number_of_entries(self): list_view_model = self.get_list_view().get_model() return len(list_view_model) def get_editing_mode(self): return self._editing_mode def set_editing_mode(self, editing_mode): if editing_mode == self._editing_mode: return self._editing_mode = editing_mode if self._editing_mode: self.get_list_view().disable_drag_and_copy() else: self.get_list_view().enable_drag_and_copy() self.show_main_view() def get_mount_point(self): return self._mount_point def _set_widgets_sensitive_state(self, sensitive_state): self._toolbox.set_sensitive(sensitive_state) self._list_view.set_sensitive(sensitive_state) if sensitive_state: self._list_view.enable_updates() else: self._list_view.disable_updates() self._volumes_toolbar.set_sensitive(sensitive_state) def freeze_ui(self): self._set_widgets_sensitive_state(False) def unfreeze_ui(self): self._set_widgets_sensitive_state(True)
class JournalActivity(JournalWindow): def __init__(self): logging.debug("STARTUP: Loading the journal") JournalWindow.__init__(self) self.set_title(_("Journal")) self._main_view = None self._secondary_view = None self._list_view = None self._detail_view = None self._main_toolbox = None self._detail_toolbox = None self._volumes_toolbar = None self._mount_point = "/" self._editing_mode = False self._setup_main_view() self._setup_secondary_view() self.add_events(Gdk.EventMask.ALL_EVENTS_MASK | Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self._realized_sid = self.connect("realize", self.__realize_cb) self.connect("visibility-notify-event", self.__visibility_notify_event_cb) self.connect("window-state-event", self.__window_state_event_cb) self.connect("key-press-event", self._key_press_event_cb) self.connect("focus-in-event", self._focus_in_event_cb) model.created.connect(self.__model_created_cb) model.updated.connect(self.__model_updated_cb) model.deleted.connect(self.__model_deleted_cb) self._dbus_service = JournalActivityDBusService(self) self.iconify() self._critical_space_alert = None self._check_available_space() session.get_session_manager().shutdown_signal.connect(self._session_manager_shutdown_cb) def volume_error_cb(self, gobject, message, severity): alert = ErrorAlert(title=severity, msg=message) alert.connect("response", self.__alert_response_cb) self.add_alert(alert) alert.show() def __alert_response_cb(self, alert, response_id): self.remove_alert(alert) def __realize_cb(self, window): xid = window.get_window().get_xid() SugarExt.wm_set_bundle_id(xid, _BUNDLE_ID) activity_id = activityfactory.create_activity_id() SugarExt.wm_set_activity_id(xid, str(activity_id)) self.disconnect(self._realized_sid) self._realized_sid = None def _session_manager_shutdown_cb(self, event): self.destroy() def can_close(self): return False def _setup_main_view(self): self._main_toolbox = MainToolbox() self._edit_toolbox = EditToolbox(self) self._main_view = Gtk.VBox() self._main_view.set_can_focus(True) self._list_view = ListView(self, enable_multi_operations=True) self._list_view.connect("detail-clicked", self.__detail_clicked_cb) self._list_view.connect("clear-clicked", self.__clear_clicked_cb) self._list_view.connect("volume-error", self.volume_error_cb) self._list_view.connect("title-edit-started", self.__title_edit_started_cb) self._list_view.connect("title-edit-finished", self.__title_edit_finished_cb) self._list_view.connect("selection-changed", self.__selection_changed_cb) self._main_view.pack_start(self._list_view, True, True, 0) self._list_view.show() self._volumes_toolbar = VolumesToolbar() self._volumes_toolbar.connect("volume-changed", self.__volume_changed_cb) self._volumes_toolbar.connect("volume-error", self.volume_error_cb) self._main_view.pack_start(self._volumes_toolbar, False, True, 0) self._main_toolbox.connect("query-changed", self._query_changed_cb) self._main_toolbox.search_entry.connect("icon-press", self.__search_icon_pressed_cb) self._main_toolbox.set_mount_point(self._mount_point) def _setup_secondary_view(self): self._secondary_view = Gtk.VBox() self._detail_toolbox = DetailToolbox(self) self._detail_toolbox.connect("volume-error", self.volume_error_cb) self._detail_view = DetailView(self) self._detail_view.connect("go-back-clicked", self.__go_back_clicked_cb) self._secondary_view.pack_end(self._detail_view, True, True, 0) self._detail_view.show() def _key_press_event_cb(self, widget, event): if not self._main_toolbox.search_entry.has_focus(): self._main_toolbox.search_entry.grab_focus() keyname = Gdk.keyval_name(event.keyval) if keyname == "Escape": self.show_main_view() def __detail_clicked_cb(self, list_view, object_id): self._show_secondary_view(object_id) def __clear_clicked_cb(self, list_view): self._main_toolbox.clear_query() def __selection_changed_cb(self, list_view, selected_items): self._editing_mode = selected_items != 0 self._edit_toolbox.set_selected_entries(selected_items) self._edit_toolbox.display_selected_entries_status() self.show_main_view() def update_selected_items_ui(self): selected_items = len(self.get_list_view().get_model().get_selected_items()) self.__selection_changed_cb(None, selected_items) def __go_back_clicked_cb(self, detail_view): self.show_main_view() def _query_changed_cb(self, toolbar, query): self._list_view.update_with_query(query) self.show_main_view() def __search_icon_pressed_cb(self, entry, icon_pos, event): self._main_view.grab_focus() def __title_edit_started_cb(self, list_view): self.disconnect_by_func(self._key_press_event_cb) def __title_edit_finished_cb(self, list_view): self.connect("key-press-event", self._key_press_event_cb) def show_main_view(self): if self._editing_mode: self._toolbox = self._edit_toolbox self._toolbox.set_total_number_of_entries(self.get_total_number_of_entries()) else: self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() if self.canvas != self._main_view: self.set_canvas(self._main_view) self._main_view.show() def _show_secondary_view(self, object_id): metadata = model.get(object_id) try: self._detail_toolbox.set_metadata(metadata) except Exception: logging.exception("Exception while displaying entry:") self.set_toolbar_box(self._detail_toolbox) self._detail_toolbox.show() try: self._detail_view.props.metadata = metadata except Exception: logging.exception("Exception while displaying entry:") self.set_canvas(self._secondary_view) self._secondary_view.show() def show_object(self, object_id): metadata = model.get(object_id) if metadata is None: return False else: self._show_secondary_view(object_id) return True def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug("Selected volume: %r.", mount_point) self._mount_point = mount_point self.set_editing_mode(False) self._main_toolbox.set_mount_point(mount_point) self._edit_toolbox.batch_copy_button.update_mount_point() def __model_created_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs["object_id"])) self._main_toolbox.refresh_filters() self._check_available_space() def __model_updated_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs["object_id"])) if self.canvas == self._secondary_view and kwargs["object_id"] == self._detail_view.props.metadata["uid"]: self._detail_view.refresh() self._check_available_space() def __model_deleted_cb(self, sender, **kwargs): if self.canvas == self._secondary_view and kwargs["object_id"] == self._detail_view.props.metadata["uid"]: self.show_main_view() def _focus_in_event_cb(self, window, event): self._list_view.update_dates() def __window_state_event_cb(self, window, event): logging.debug("window_state_event_cb %r", self) if event.changed_mask & Gdk.WindowState.ICONIFIED: state = event.new_window_state visible = not state & Gdk.WindowState.ICONIFIED self._list_view.set_is_visible(visible) def __visibility_notify_event_cb(self, window, event): logging.debug("visibility_notify_event_cb %r", self) visible = event.get_state() != Gdk.VisibilityState.FULLY_OBSCURED self._list_view.set_is_visible(visible) def _check_available_space(self): """Check available space on device If the available space is below 50MB an alert will be shown which encourages to delete old journal entries. """ if self._critical_space_alert: return stat = os.statvfs(env.get_profile_path()) free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] if free_space < _SPACE_TRESHOLD: self._critical_space_alert = ModalAlert() self._critical_space_alert.connect("destroy", self.__alert_closed_cb) self._critical_space_alert.show() def __alert_closed_cb(self, data): self.show_main_view() self.reveal() self._critical_space_alert = None def set_active_volume(self, mount): self._volumes_toolbar.set_active_volume(mount) def show_journal(self): """Become visible and show main view""" self.reveal() self.show_main_view() def get_list_view(self): return self._list_view def get_total_number_of_entries(self): list_view_model = self.get_list_view().get_model() return len(list_view_model) def get_editing_mode(self): return self._editing_mode def set_editing_mode(self, editing_mode): if editing_mode == self._editing_mode: return self._editing_mode = editing_mode if self._editing_mode: self.get_list_view().disable_drag_and_copy() else: self.get_list_view().enable_drag_and_copy() self.show_main_view() def get_mount_point(self): return self._mount_point def _set_widgets_sensitive_state(self, sensitive_state): self._toolbox.set_sensitive(sensitive_state) self._list_view.set_sensitive(sensitive_state) if sensitive_state: self._list_view.enable_updates() else: self._list_view.disable_updates() self._volumes_toolbar.set_sensitive(sensitive_state) def freeze_ui(self): self._set_widgets_sensitive_state(False) def unfreeze_ui(self): self._set_widgets_sensitive_state(True)
class JournalActivity(JournalWindow): def __init__(self): logging.debug('STARTUP: Loading the journal') JournalWindow.__init__(self) self.set_title(_('Journal')) self._main_view = None self._secondary_view = None self._list_view = None self._detail_view = None self._main_toolbox = None self._detail_toolbox = None self._volumes_toolbar = None self._mount_point = '/' self._editing_mode = False self._setup_main_view() self._setup_secondary_view() self.add_events(Gdk.EventMask.ALL_EVENTS_MASK | Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self._realized_sid = self.connect('realize', self.__realize_cb) self.connect('visibility-notify-event', self.__visibility_notify_event_cb) self.connect('window-state-event', self.__window_state_event_cb) self.connect('key-press-event', self._key_press_event_cb) self.connect('focus-in-event', self._focus_in_event_cb) model.created.connect(self.__model_created_cb) model.updated.connect(self.__model_updated_cb) model.deleted.connect(self.__model_deleted_cb) self._dbus_service = JournalActivityDBusService(self) self.iconify() self._critical_space_alert = None self._check_available_space() session.get_session_manager().shutdown_signal.connect( self._session_manager_shutdown_cb) def volume_error_cb(self, gobject, message, severity): alert = ErrorAlert(title=severity, msg=message) alert.connect('response', self.__alert_response_cb) self.add_alert(alert) alert.show() def __alert_response_cb(self, alert, response_id): self.remove_alert(alert) def __realize_cb(self, window): xid = window.get_window().get_xid() SugarExt.wm_set_bundle_id(xid, _BUNDLE_ID) activity_id = activityfactory.create_activity_id() SugarExt.wm_set_activity_id(xid, str(activity_id)) self.disconnect(self._realized_sid) self._realized_sid = None def _session_manager_shutdown_cb(self, event): self.destroy() def can_close(self): return False def _setup_main_view(self): self._main_toolbox = MainToolbox() self._edit_toolbox = EditToolbox(self) self._main_view = Gtk.VBox() self._main_view.set_can_focus(True) self._list_view = ListView(self, enable_multi_operations=True) self._list_view.connect('detail-clicked', self.__detail_clicked_cb) self._list_view.connect('clear-clicked', self.__clear_clicked_cb) self._list_view.connect('volume-error', self.volume_error_cb) self._list_view.connect('title-edit-started', self.__title_edit_started_cb) self._list_view.connect('title-edit-finished', self.__title_edit_finished_cb) self._list_view.connect('selection-changed', self.__selection_changed_cb) self._main_view.pack_start(self._list_view, True, True, 0) self._list_view.show() self._volumes_toolbar = VolumesToolbar() self._volumes_toolbar.connect('volume-changed', self.__volume_changed_cb) self._volumes_toolbar.connect('volume-error', self.volume_error_cb) self._main_view.pack_start(self._volumes_toolbar, False, True, 0) self._main_toolbox.connect('query-changed', self._query_changed_cb) self._main_toolbox.search_entry.connect('icon-press', self.__search_icon_pressed_cb) self._main_toolbox.set_mount_point(self._mount_point) def _setup_secondary_view(self): self._secondary_view = Gtk.VBox() self._detail_toolbox = DetailToolbox(self) self._detail_toolbox.connect('volume-error', self.volume_error_cb) self._detail_view = DetailView(self) self._detail_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._secondary_view.pack_end(self._detail_view, True, True, 0) self._detail_view.show() def _key_press_event_cb(self, widget, event): if not self._main_toolbox.search_entry.has_focus(): self._main_toolbox.search_entry.grab_focus() keyname = Gdk.keyval_name(event.keyval) if keyname == 'Escape': self.show_main_view() def __detail_clicked_cb(self, list_view, object_id): self._show_secondary_view(object_id) def __clear_clicked_cb(self, list_view): self._main_toolbox.clear_query() def __selection_changed_cb(self, list_view, selected_items): self._editing_mode = selected_items != 0 self._edit_toolbox.set_selected_entries(selected_items) self._edit_toolbox.display_selected_entries_status() self.show_main_view() def update_selected_items_ui(self): selected_items = \ len(self.get_list_view().get_model().get_selected_items()) self.__selection_changed_cb(None, selected_items) def __go_back_clicked_cb(self, detail_view): self.show_main_view() def _query_changed_cb(self, toolbar, query): self._list_view.update_with_query(query) self.show_main_view() def __search_icon_pressed_cb(self, entry, icon_pos, event): self._main_view.grab_focus() def __title_edit_started_cb(self, list_view): self.disconnect_by_func(self._key_press_event_cb) def __title_edit_finished_cb(self, list_view): self.connect('key-press-event', self._key_press_event_cb) def show_main_view(self): if self._editing_mode: self._toolbox = self._edit_toolbox self._toolbox.set_total_number_of_entries( self.get_total_number_of_entries()) else: self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() if self.canvas != self._main_view: self.set_canvas(self._main_view) self._main_view.show() def _show_secondary_view(self, object_id): metadata = model.get(object_id) try: self._detail_toolbox.set_metadata(metadata) except Exception: logging.exception('Exception while displaying entry:') self.set_toolbar_box(self._detail_toolbox) self._detail_toolbox.show() try: self._detail_view.props.metadata = metadata except Exception: logging.exception('Exception while displaying entry:') self.set_canvas(self._secondary_view) self._secondary_view.show() def show_object(self, object_id): metadata = model.get(object_id) if metadata is None: return False else: self._show_secondary_view(object_id) return True def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug('Selected volume: %r.', mount_point) self._mount_point = mount_point self.set_editing_mode(False) self._main_toolbox.set_mount_point(mount_point) self._edit_toolbox.batch_copy_button.update_mount_point() def __model_created_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) self._main_toolbox.refresh_filters() self._check_available_space() def __model_updated_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self._detail_view.refresh() self._check_available_space() def __model_deleted_cb(self, sender, **kwargs): if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self.show_main_view() def _focus_in_event_cb(self, window, event): self._list_view.update_dates() def __window_state_event_cb(self, window, event): logging.debug('window_state_event_cb %r', self) if event.changed_mask & Gdk.WindowState.ICONIFIED: state = event.new_window_state visible = not state & Gdk.WindowState.ICONIFIED self._list_view.set_is_visible(visible) def __visibility_notify_event_cb(self, window, event): logging.debug('visibility_notify_event_cb %r', self) visible = event.get_state() != Gdk.VisibilityState.FULLY_OBSCURED self._list_view.set_is_visible(visible) def _check_available_space(self): """Check available space on device If the available space is below 50MB an alert will be shown which encourages to delete old journal entries. """ if self._critical_space_alert: return stat = os.statvfs(env.get_profile_path()) free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] if free_space < _SPACE_TRESHOLD: self._critical_space_alert = ModalAlert() self._critical_space_alert.connect('destroy', self.__alert_closed_cb) self._critical_space_alert.show() def __alert_closed_cb(self, data): self.show_main_view() self.reveal() self._critical_space_alert = None def set_active_volume(self, mount): self._volumes_toolbar.set_active_volume(mount) def show_journal(self): """Become visible and show main view""" self.reveal() self.show_main_view() def get_list_view(self): return self._list_view def get_total_number_of_entries(self): list_view_model = self.get_list_view().get_model() return len(list_view_model) def get_editing_mode(self): return self._editing_mode def set_editing_mode(self, editing_mode): if editing_mode == self._editing_mode: return self._editing_mode = editing_mode if self._editing_mode: self.get_list_view().disable_drag_and_copy() else: self.get_list_view().enable_drag_and_copy() self.show_main_view() def get_mount_point(self): return self._mount_point def _set_widgets_sensitive_state(self, sensitive_state): self._toolbox.set_sensitive(sensitive_state) self._list_view.set_sensitive(sensitive_state) if sensitive_state: self._list_view.enable_updates() else: self._list_view.disable_updates() self._volumes_toolbar.set_sensitive(sensitive_state) def freeze_ui(self): self._set_widgets_sensitive_state(False) def unfreeze_ui(self): self._set_widgets_sensitive_state(True)
class JournalActivity(JournalWindow): def __init__(self): logging.debug('STARTUP: Loading the journal') JournalWindow.__init__(self) self.set_title(_('Journal')) self._main_view = None self._project_view = None self._secondary_view = None self._list_view = None self._detail_view = None self._main_toolbox = None self._detail_toolbox = None self._volumes_toolbar = None self._mount_point = '/' self._active_view = JournalViews.MAIN self.project_metadata = None self._editing_mode = False self._setup_main_view() self._setup_secondary_view() self._setup_project_view() self.add_events(Gdk.EventMask.ALL_EVENTS_MASK) self._realized_sid = self.connect('realize', self.__realize_cb) self.connect('window-state-event', self.__window_state_event_cb) self.connect('key-press-event', self.__key_press_event_cb) self.connect('focus-in-event', self._focus_in_event_cb) self.connect('focus-out-event', self._focus_out_event_cb) model.created.connect(self.__model_created_cb) model.updated.connect(self.__model_updated_cb) model.deleted.connect(self.__model_deleted_cb) self._dbus_service = JournalActivityDBusService(self) self.iconify() self._critical_space_alert = None self._check_available_space() session.get_session_manager().shutdown_signal.connect( self._session_manager_shutdown_cb) def volume_error_cb(self, gobject, message, severity): alert = ErrorAlert(title=severity, msg=message) alert.connect('response', self.__alert_response_cb) self.add_alert(alert) alert.show() def __alert_response_cb(self, alert, response_id): self.remove_alert(alert) def __realize_cb(self, window): xid = window.get_window().get_xid() SugarExt.wm_set_bundle_id(xid, _BUNDLE_ID) activity_id = activityfactory.create_activity_id() SugarExt.wm_set_activity_id(xid, str(activity_id)) self.disconnect(self._realized_sid) self._realized_sid = None def _session_manager_shutdown_cb(self, event): self.destroy() def can_close(self): return False def list_view_signal_connect(self, list_view): list_view.connect('detail-clicked', self.__detail_clicked_cb) list_view.connect('clear-clicked', self.__clear_clicked_cb) list_view.connect('volume-error', self.volume_error_cb) list_view.connect('title-edit-started', self.__title_edit_started_cb) list_view.connect('title-edit-finished', self.__title_edit_finished_cb) list_view.connect('selection-changed', self.__selection_changed_cb) list_view.connect('project-view-activate', self.project_view_activated_cb) def _create_volumes_toolbar(self): self._volumes_toolbar = VolumesToolbar() self._volumes_toolbar.connect('volume-changed', self.__volume_changed_cb) self._volumes_toolbar.connect('volume-error', self.volume_error_cb) return self._volumes_toolbar def _setup_main_view(self): self._main_toolbox = MainToolbox() self._edit_toolbox = EditToolbox(self) self._main_view = Gtk.VBox() self._add_new_box = AddNewBar(_('Add new project')) self._add_new_box.activate.connect(self.__add_project_activate_cb) self._main_view.pack_start(self._add_new_box, False, True, style.DEFAULT_SPACING) self._main_view.set_can_focus(True) self._list_view = ListView(self, enable_multi_operations=True) self.list_view_signal_connect(self._list_view) tree_view = self._list_view.tree_view tree_view.connect('choose-project', self.__choose_project_cb) self._main_view.pack_start(self._list_view, True, True, 0) self._list_view.show_all() volumes_toolbar = self._create_volumes_toolbar() self._main_view.pack_start(volumes_toolbar, False, True, 0) self._main_toolbox.connect('query-changed', self._query_changed_cb) self._main_toolbox.search_entry.connect('icon-press', self.__search_icon_pressed_cb) self._main_toolbox.set_mount_point(self._mount_point) def _setup_project_view(self): self._project_view = ProjectView() project_vbox = self._project_view.get_vbox() add_new_box = AddNewBar() add_new_box.activate.connect(self.__add_new_activate_cb) add_new_box.show_all() project_vbox.pack_start(add_new_box, False, True, style.DEFAULT_SPACING/3) self._entry_project = add_new_box.get_entry() self._list_view_project = self._project_view.create_list_view_project() self.list_view_signal_connect(self._list_view_project) project_vbox.pack_start(self._list_view_project, True, True, 0) self._list_view_project.show() def get_add_new_box(self): return self._add_new_box def get_list_view(self): return self._list_view def project_view_activated_cb(self, list_view, metadata): self.project_metadata = metadata self._project_view.set_project_metadata(self.project_metadata) self._project_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._active_view = JournalViews.PROJECT self.set_canvas(self._project_view) self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() query = {} query['project_id'] = self.project_metadata['uid'] self._list_view_project.update_with_query(query) self._project_view.show_all() def _setup_secondary_view(self): self._secondary_view = Gtk.VBox() self._detail_toolbox = DetailToolbox(self) self._detail_toolbox.connect('volume-error', self.volume_error_cb) self._detail_view = DetailView(self) self._detail_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._secondary_view.pack_end(self._detail_view, True, True, 0) self._detail_view.show() def __add_project_activate_cb(self, bar, title): initialize_journal_object( title=title, bundle_id=PROJECT_BUNDLE_ID, activity_id=None, project_metadata=None) def __add_new_activate_cb(self, bar, title): chooser = ActivityChooser() text = _("Choose an activity to start '%s' with") % title chooser.set_title(text) chooser.connect('activity-selected', self.__activity_selected_cb, title) chooser.show_all() def __activity_selected_cb(self, widget, bundle_id, activity_id, title): initialize_journal_object( title=title, bundle_id=bundle_id, activity_id=activity_id, project_metadata=self.project_metadata) def __key_press_event_cb(self, widget, event): #if not self._main_toolbox.search_entry.has_focus(): #self._main_toolbox.search_entry.grab_focus() keyname = Gdk.keyval_name(event.keyval) if keyname == 'Escape': self._main_toolbox.clear_query() self.show_main_view() def __choose_project_cb(self, tree_view, metadata_to_send): project_chooser = ObjectChooser(self.get_window()) project_chooser.show_all() project_chooser.connect('response', self.__project_chooser_response_cb, metadata_to_send) project_chooser._toolbar._proj_list_button_clicked_cb(None) def __project_chooser_response_cb(self, project_chooser, response_value, metadata_to_send): if response_value == Gtk.ResponseType.DELETE_EVENT: project_chooser.destroy() return object_id = project_chooser.get_selected_object_id() metadata = model.get(object_id) jobject_to_send = datastore.get(metadata_to_send['uid']) datastore.delete(metadata_to_send['uid']) jobject_to_send.metadata['project_id'] = metadata['uid'] datastore.write(jobject_to_send) project_chooser.destroy() def __detail_clicked_cb(self, list_view, object_id): metadata = model.get(object_id) activity = metadata.get('activity', None) if activity == PROJECT_BUNDLE_ID: self.project_view_activated_cb(list_view, metadata) else: self._show_secondary_view(object_id) def __clear_clicked_cb(self, list_view): self._main_toolbox.clear_query() def __selection_changed_cb(self, list_view, selected_items): self._editing_mode = selected_items != 0 self._edit_toolbox.set_selected_entries(selected_items) self._edit_toolbox.display_selected_entries_status() self.show_main_view() def update_selected_items_ui(self): selected_items = \ len(self.get_list_view().get_model().get_selected_items()) self.__selection_changed_cb(None, selected_items) def __go_back_clicked_cb(self, detail_view): self.show_main_view() def _query_changed_cb(self, toolbar, query): self._list_view.update_with_query(query) self.show_main_view() self._add_new_box.props.visible = \ query.get('activity') == PROJECT_BUNDLE_ID def __search_icon_pressed_cb(self, entry, icon_pos, event): self._main_view.grab_focus() def __title_edit_started_cb(self, list_view): self.disconnect_by_func(self.__key_press_event_cb) def __title_edit_finished_cb(self, list_view): self.connect('key-press-event', self.__key_press_event_cb) def show_main_view(self): self._active_view = JournalViews.MAIN self.project_metadata = None if self._editing_mode: self._toolbox = self._edit_toolbox self._toolbox.set_total_number_of_entries( self.get_total_number_of_entries()) else: self._toolbox = self._main_toolbox self.set_toolbar_box(self._toolbox) self._toolbox.show() if self.canvas != self._main_view: self.set_canvas(self._main_view) self._main_view.show() def _show_secondary_view(self, object_id): self._active_view = JournalViews.DETAIL metadata = model.get(object_id) try: self._detail_toolbox.set_metadata(metadata) except Exception: logging.exception('Exception while displaying entry:') self.set_toolbar_box(self._detail_toolbox) self._detail_toolbox.show() try: self._detail_view.props.metadata = metadata except Exception: logging.exception('Exception while displaying entry:') self.set_canvas(self._secondary_view) self._secondary_view.show() def show_object(self, object_id): metadata = model.get(object_id) if metadata is None: return False else: self._show_secondary_view(object_id) return True def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug('Selected volume: %r.', mount_point) self._mount_point = mount_point self.set_editing_mode(False) self._main_toolbox.set_mount_point(mount_point) self._edit_toolbox.batch_copy_button.update_mount_point() def __model_created_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) self._main_toolbox.refresh_filters() self._check_available_space() def __model_updated_cb(self, sender, **kwargs): misc.handle_bundle_installation(model.get(kwargs['object_id'])) if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self._detail_view.refresh() self._check_available_space() def __model_deleted_cb(self, sender, **kwargs): if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self.show_main_view() def _focus_in_event_cb(self, window, event): self._set_is_visible(True) def _focus_out_event_cb(self, window, event): self._set_is_visible(False) def __window_state_event_cb(self, window, event): logging.debug('window_state_event_cb %r', self) if event.changed_mask & Gdk.WindowState.ICONIFIED: state = event.new_window_state visible = not state & Gdk.WindowState.ICONIFIED self._set_is_visible(visible) def _set_is_visible(self, visible): if self._active_view == JournalViews.MAIN: self._list_view.set_is_visible(visible) elif self._active_view == JournalViews.PROJECT: self._list_view_project.set_is_visible(visible) def _check_available_space(self): """Check available space on device If the available space is below threshold an alert will be shown which suggests deleting old journal entries. """ if self._critical_space_alert: return stat = os.statvfs(env.get_profile_path()) free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] if free_space < (_SPACE_THRESHOLD * 1024 * 1024): self._critical_space_alert = ModalAlert() self._critical_space_alert.connect('destroy', self.__alert_closed_cb) self._critical_space_alert.show() def __alert_closed_cb(self, data): self.show_main_view() self.reveal() self._critical_space_alert = None def set_active_volume(self, mount): self._volumes_toolbar.set_active_volume(mount) def show_journal(self): """Become visible and show main view""" self.reveal() self.show_main_view() def get_total_number_of_entries(self): list_view_model = self.get_list_view().get_model() return len(list_view_model) def get_editing_mode(self): return self._editing_mode def set_editing_mode(self, editing_mode): if editing_mode == self._editing_mode: return self._editing_mode = editing_mode if self._editing_mode: self.get_list_view().disable_drag_and_copy() else: self.get_list_view().enable_drag_and_copy() self.show_main_view() def get_mount_point(self): return self._mount_point def _set_widgets_sensitive_state(self, sensitive_state): self._toolbox.set_sensitive(sensitive_state) self._list_view.set_sensitive(sensitive_state) if sensitive_state: self._list_view.enable_updates() else: self._list_view.disable_updates() self._volumes_toolbar.set_sensitive(sensitive_state) def freeze_ui(self): self._set_widgets_sensitive_state(False) def unfreeze_ui(self): self._set_widgets_sensitive_state(True)
class JournalActivity(JournalWindow): def __init__(self): logging.debug('STARTUP: Loading the journal') JournalWindow.__init__(self) self.set_title(_('Journal')) self._main_view = None self._secondary_view = None self._list_view = None self._detail_view = None self._main_toolbox = None self._detail_toolbox = None self._volumes_toolbar = None self._setup_main_view() self._setup_secondary_view() self.add_events(Gdk.EventMask.ALL_EVENTS_MASK | Gdk.EventMask.VISIBILITY_NOTIFY_MASK) self._realized_sid = self.connect('realize', self.__realize_cb) self.connect('visibility-notify-event', self.__visibility_notify_event_cb) self.connect('window-state-event', self.__window_state_event_cb) self.connect('key-press-event', self._key_press_event_cb) self.connect('focus-in-event', self._focus_in_event_cb) model.created.connect(self.__model_created_cb) model.updated.connect(self.__model_updated_cb) model.deleted.connect(self.__model_deleted_cb) self._dbus_service = JournalActivityDBusService(self) self.iconify() self._critical_space_alert = None self._check_available_space() def __volume_error_cb(self, gobject, message, severity): alert = ErrorAlert(title=severity, msg=message) alert.connect('response', self.__alert_response_cb) self.add_alert(alert) alert.show() def __alert_response_cb(self, alert, response_id): self.remove_alert(alert) def __realize_cb(self, window): xid = window.get_window().get_xid() SugarExt.wm_set_bundle_id(xid, _BUNDLE_ID) activity_id = activityfactory.create_activity_id() SugarExt.wm_set_activity_id(xid, str(activity_id)) self.disconnect(self._realized_sid) self._realized_sid = None def can_close(self): return False def _setup_main_view(self): self._main_toolbox = MainToolbox() self._main_view = Gtk.VBox() self._main_view.set_can_focus(True) self._list_view = ListView() self._list_view.connect('detail-clicked', self.__detail_clicked_cb) self._list_view.connect('clear-clicked', self.__clear_clicked_cb) self._list_view.connect('volume-error', self.__volume_error_cb) self._list_view.connect('title-edit-started', self.__title_edit_started_cb) self._list_view.connect('title-edit-finished', self.__title_edit_finished_cb) self._main_view.pack_start(self._list_view, True, True, 0) self._list_view.show() self._volumes_toolbar = VolumesToolbar() self._volumes_toolbar.connect('volume-changed', self.__volume_changed_cb) self._volumes_toolbar.connect('volume-error', self.__volume_error_cb) self._main_view.pack_start(self._volumes_toolbar, False, True, 0) self._main_toolbox.connect('query-changed', self._query_changed_cb) self._main_toolbox.search_entry.connect('icon-press', self.__search_icon_pressed_cb) self._main_toolbox.set_mount_point('/') def _setup_secondary_view(self): self._secondary_view = Gtk.VBox() self._detail_toolbox = DetailToolbox() self._detail_toolbox.connect('volume-error', self.__volume_error_cb) self._detail_view = DetailView() self._detail_view.connect('go-back-clicked', self.__go_back_clicked_cb) self._secondary_view.pack_end(self._detail_view, True, True, 0) self._detail_view.show() def _key_press_event_cb(self, widget, event): if not self._main_toolbox.search_entry.has_focus(): self._main_toolbox.search_entry.grab_focus() keyname = Gdk.keyval_name(event.keyval) if keyname == 'Escape': self.show_main_view() def __detail_clicked_cb(self, list_view, object_id): self._show_secondary_view(object_id) def __clear_clicked_cb(self, list_view): self._main_toolbox.clear_query() def __go_back_clicked_cb(self, detail_view): self.show_main_view() def _query_changed_cb(self, toolbar, query): self._list_view.update_with_query(query) self.show_main_view() def __search_icon_pressed_cb(self, entry, icon_pos, event): self._main_view.grab_focus() def __title_edit_started_cb(self, list_view): self.disconnect_by_func(self._key_press_event_cb) def __title_edit_finished_cb(self, list_view): self.connect('key-press-event', self._key_press_event_cb) def show_main_view(self): if self.toolbar_box != self._main_toolbox: self.set_toolbar_box(self._main_toolbox) self._main_toolbox.show() if self.canvas != self._main_view: self.set_canvas(self._main_view) self._main_view.show() def _show_secondary_view(self, object_id): metadata = model.get(object_id) try: self._detail_toolbox.set_metadata(metadata) except Exception: logging.exception('Exception while displaying entry:') self.set_toolbar_box(self._detail_toolbox) self._detail_toolbox.show() try: self._detail_view.props.metadata = metadata except Exception: logging.exception('Exception while displaying entry:') self.set_canvas(self._secondary_view) self._secondary_view.show() def show_object(self, object_id): metadata = model.get(object_id) if metadata is None: return False else: self._show_secondary_view(object_id) return True def __volume_changed_cb(self, volume_toolbar, mount_point): logging.debug('Selected volume: %r.', mount_point) self._main_toolbox.set_mount_point(mount_point) def __model_created_cb(self, sender, **kwargs): self._check_for_bundle(kwargs['object_id']) self._main_toolbox.refresh_filters() self._check_available_space() def __model_updated_cb(self, sender, **kwargs): self._check_for_bundle(kwargs['object_id']) if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self._detail_view.refresh() self._check_available_space() def __model_deleted_cb(self, sender, **kwargs): if self.canvas == self._secondary_view and \ kwargs['object_id'] == self._detail_view.props.metadata['uid']: self.show_main_view() def _focus_in_event_cb(self, window, event): self._list_view.update_dates() def _check_for_bundle(self, object_id): registry = bundleregistry.get_registry() metadata = model.get(object_id) if metadata.get('progress', '').isdigit(): if int(metadata['progress']) < 100: return bundle = misc.get_bundle(metadata) if bundle is None: return if registry.is_installed(bundle): logging.debug('_check_for_bundle bundle already installed') return if metadata['mime_type'] == JournalEntryBundle.MIME_TYPE: # JournalEntryBundle code takes over the datastore entry and # transforms it into the journal entry from the bundle -- we have # nothing more to do. try: registry.install(bundle, metadata['uid']) except (ZipExtractException, RegistrationException): logging.exception('Could not install bundle %s', bundle.get_path()) return try: registry.install(bundle) except (ZipExtractException, RegistrationException): logging.exception('Could not install bundle %s', bundle.get_path()) return metadata['bundle_id'] = bundle.get_bundle_id() model.write(metadata) def __window_state_event_cb(self, window, event): logging.debug('window_state_event_cb %r', self) if event.changed_mask & Gdk.WindowState.ICONIFIED: state = event.new_window_state visible = not state & Gdk.WindowState.ICONIFIED self._list_view.set_is_visible(visible) def __visibility_notify_event_cb(self, window, event): logging.debug('visibility_notify_event_cb %r', self) visible = event.get_state() != Gdk.VisibilityState.FULLY_OBSCURED self._list_view.set_is_visible(visible) def _check_available_space(self): """Check available space on device If the available space is below 50MB an alert will be shown which encourages to delete old journal entries. """ if self._critical_space_alert: return stat = os.statvfs(env.get_profile_path()) free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] if free_space < _SPACE_TRESHOLD: self._critical_space_alert = ModalAlert() self._critical_space_alert.connect('destroy', self.__alert_closed_cb) self._critical_space_alert.show() def __alert_closed_cb(self, data): self.show_main_view() self.reveal() self._critical_space_alert = None def set_active_volume(self, mount): self._volumes_toolbar.set_active_volume(mount) def show_journal(self): """Become visible and show main view""" self.reveal() self.show_main_view()