def __init__(self, handle, create_jobject=True): if hasattr(GLib, 'unix_signal_add'): GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.close) icons_path = os.path.join(self._get_bundle_path(), 'icons') Gtk.IconTheme.get_default().append_search_path(icons_path) sugar_theme = 'sugar-72' if 'SUGAR_SCALING' in os.environ: if os.environ['SUGAR_SCALING'] == '100': sugar_theme = 'sugar-100' settings = Gtk.Settings.get_default() settings.set_property('gtk-theme-name', sugar_theme) settings.set_property('gtk-icon-theme-name', 'sugar') settings.set_property('gtk-button-images', True) settings.set_property('gtk-font-name', '%s %f' % (style.FONT_FACE, style.FONT_SIZE)) SugarCompatibleWindow.__init__(self) self._handle = handle self._read_file_called = False bundle = get_bundle_instance(self._get_bundle_path()) self.set_icon_from_file(bundle.get_icon()) self._restore_metadata()
def get_icon_name(metadata): file_name = None bundle_id = metadata.get('activity', '') if not bundle_id: bundle_id = metadata.get('bundle_id', '') if bundle_id: activity_info = bundleregistry.get_registry().get_bundle(bundle_id) if activity_info: file_name = activity_info.get_icon() if file_name is None and is_activity_bundle(metadata): file_path = model.get_file(metadata['uid']) if file_path is not None and os.path.exists(file_path): try: bundle = get_bundle_instance(file_path) file_name = bundle.get_icon() except Exception: logging.exception('Could not read bundle') if file_name is None: file_name = _get_icon_for_mime(metadata.get('mime_type', '')) if file_name is None: file_name = get_icon_file_name('application-octet-stream') return file_name
def get_icon_name(metadata): file_name = None bundle_id = metadata.get('activity', '') if not bundle_id: bundle_id = metadata.get('bundle_id', '') if bundle_id: if bundle_id == PROJECT_BUNDLE_ID: file_name = \ '/home/broot/sugar-build/build' + \ '/out/install/share/icons/sugar/' + \ 'scalable/mimetypes/project-box.svg' return file_name activity_info = bundleregistry.get_registry().get_bundle(bundle_id) if activity_info: file_name = activity_info.get_icon() if file_name is None and is_activity_bundle(metadata): file_path = model.get_file(metadata['uid']) if file_path is not None and os.path.exists(file_path): try: bundle = get_bundle_instance(file_path) file_name = bundle.get_icon() except Exception: logging.exception('Could not read bundle') if file_name is None: file_name = _get_icon_for_mime(metadata.get('mime_type', '')) if file_name is None: file_name = get_icon_file_name('application-octet-stream') return file_name
def get_bundle(metadata): try: if is_activity_bundle(metadata): file_path = model.get_file(metadata['uid']) if not os.path.exists(file_path): logging.warning('Invalid path: %r', file_path) return None return get_bundle_instance(file_path) elif is_content_bundle(metadata): file_path = model.get_file(metadata['uid']) if not os.path.exists(file_path): logging.warning('Invalid path: %r', file_path) return None return ContentBundle(file_path) elif is_journal_bundle(metadata): file_path = model.get_file(metadata['uid']) if not os.path.exists(file_path): logging.warning('Invalid path: %r', file_path) return None return JournalEntryBundle(file_path, metadata['uid']) else: return None except Exception: logging.exception('Incorrect bundle') return None
def get_max_participants(self): # If max_participants has not been set in the activity, get it # from the bundle. if self._max_participants is None: bundle = get_bundle_instance(get_bundle_path()) self._max_participants = bundle.get_max_participants() return self._max_participants
def _create_activity_icon(metadata): if metadata is not None and metadata.get('icon-color'): color = XoColor(metadata['icon-color']) else: color = profile.get_color() from sugar3.activity.activity import get_bundle_path bundle = get_bundle_instance(get_bundle_path()) icon = Icon(file=bundle.get_icon(), xo_color=color) return icon
def get_max_participants(self): ''' Returns: int: the max number of users than can share a instance of the activity. Should be configured in the activity.info file. ''' # If max_participants has not been set in the activity, get it # from the bundle. if self._max_participants is None: bundle = get_bundle_instance(get_bundle_path()) self._max_participants = bundle.get_max_participants() return self._max_participants
def notify_user(self, summary, body): ''' Display a notification with the given summary and body. The notification will go under the activities icon in the frame. ''' bundle = get_bundle_instance(get_bundle_path()) icon = bundle.get_icon() bus = dbus.SessionBus() notify_obj = bus.get_object(N_BUS_NAME, N_OBJ_PATH) notifications = dbus.Interface(notify_obj, N_IFACE_NAME) notifications.Notify(self.get_id(), 0, '', summary, body, [], {'x-sugar-icon-file-name': icon}, -1)
def get_help_url_and_title(activity): """ Returns the help document name and the title to display, or None if not content is available. """ bundle_path = activity.get_bundle_path() if bundle_path is None: shell_model = shell.get_model() zoom_level = shell_model.zoom_level if zoom_level == shell_model.ZOOM_MESH: title = _('Mesh') link_id = 'mesh_view' elif zoom_level == shell_model.ZOOM_GROUP: title = _('Group') link_id = 'group_view' elif zoom_level == shell_model.ZOOM_HOME: title = _('Home') link_id = 'home_view' else: title = _('Journal') link_id = 'org.laptop.JournalActivity' else: # get activity name and window id activity_bundle = get_bundle_instance(bundle_path) title = activity_bundle.get_name() link_id = activity_bundle.get_bundle_id() # get the help file name for the activity activity_path = _get_help_activity_path() if activity_path is None: return None, title help_content_link = os.path.join(activity_path, 'helplink.json') if not os.path.exists(help_content_link): _logger.error('Help activity not installed or json file not found') return None, title links = None try: with open(help_content_link) as json_file: links = json.load(json_file) except IOError: _logger.error('helplink.json malformed, or can\'t be read') if links: if link_id in links.keys(): return links[link_id], title return None, title
def get_help_url_and_title(activity): """ Returns the help document name and the title to display, or None if not content is available. """ bundle_path = activity.get_bundle_path() if bundle_path is None: shell_model = shell.get_model() zoom_level = shell_model.zoom_level if zoom_level == shell_model.ZOOM_MESH: title = _("Mesh") link_id = "mesh_view" elif zoom_level == shell_model.ZOOM_GROUP: title = _("Group") link_id = "group_view" elif zoom_level == shell_model.ZOOM_HOME: title = _("Home") link_id = "home_view" else: title = _("Journal") link_id = "org.laptop.JournalActivity" else: # get activity name and window id activity_bundle = get_bundle_instance(bundle_path) title = activity_bundle.get_name() link_id = activity_bundle.get_bundle_id() # get the help file name for the activity activity_path = _get_help_activity_path() if activity_path is None: return None, title help_content_link = os.path.join(activity_path, "helplink.json") if not os.path.exists(help_content_link): _logger.error("Help activity not installed or json file not found") return None, title links = None try: with open(help_content_link) as json_file: links = json.load(json_file) except IOError: _logger.error("helplink.json malformed, or can't be read") if links: if link_id in links.keys(): return links[link_id], title return None, title
def __init__(self, title, bundle_path, document_path, sugar_toolkit_path): Gtk.Toolbar.__init__(self) document_button = None self.bundle_path = bundle_path self.sugar_toolkit_path = sugar_toolkit_path self._add_separator() activity_bundle = get_bundle_instance(bundle_path) file_name = activity_bundle.get_icon() activity_name = activity_bundle.get_name() if document_path is not None and os.path.exists(document_path): document_button = DocumentButton(file_name, document_path, activity_name, title) document_button.connect('toggled', self.__button_toggled_cb, document_path) self.insert(document_button, -1) document_button.show() self._add_separator() if bundle_path is not None and os.path.exists(bundle_path): activity_button = DocumentButton(file_name, bundle_path, activity_name, title, bundle=True) icon = Icon(file=file_name, pixel_size=style.STANDARD_ICON_SIZE, fill_color=style.COLOR_TRANSPARENT.get_svg(), stroke_color=style.COLOR_WHITE.get_svg()) activity_button.set_icon_widget(icon) icon.show() if document_button is not None: activity_button.props.group = document_button activity_button.props.tooltip = _('Activity Bundle Source') activity_button.connect('toggled', self.__button_toggled_cb, bundle_path) self.insert(activity_button, -1) activity_button.show() self._add_separator() if sugar_toolkit_path is not None: sugar_button = RadioToolButton() icon = Icon(icon_name='computer-xo', pixel_size=style.STANDARD_ICON_SIZE, fill_color=style.COLOR_TRANSPARENT.get_svg(), stroke_color=style.COLOR_WHITE.get_svg()) sugar_button.set_icon_widget(icon) icon.show() if document_button is not None: sugar_button.props.group = document_button else: sugar_button.props.group = activity_button sugar_button.props.tooltip = _('Sugar Toolkit Source') sugar_button.connect('toggled', self.__button_toggled_cb, sugar_toolkit_path) self.insert(sugar_button, -1) sugar_button.show() self._add_separator() self.activity_title_text = _('View source: %s') % title self.sugar_toolkit_title_text = _('View source: %r') % 'Sugar Toolkit' self.label = Gtk.Label() self.label.set_markup('<b>%s</b>' % self.activity_title_text) self.label.set_ellipsize(style.ELLIPSIZE_MODE_DEFAULT) self.label.set_alignment(0, 0.5) self._add_widget(self.label, expand=True) self._add_separator(False) stop = ToolButton(icon_name='dialog-cancel') stop.set_tooltip(_('Close')) stop.connect('clicked', self.__stop_clicked_cb) self.insert(stop, -1) stop.show()
def __init__(self, window_xid, bundle_path, document_path, sugar_toolkit_path, title): Gtk.Window.__init__(self) _logger.debug('ViewSource paths: %r %r %r', bundle_path, document_path, sugar_toolkit_path) self.set_modal(True) self.set_decorated(False) self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.set_border_width(style.LINE_WIDTH) self.set_has_resize_grip(False) width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2 height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2 self.set_size_request(width, height) self._parent_window_xid = window_xid self._sugar_toolkit_path = sugar_toolkit_path self._gdk_window = self.get_root_window() self.connect('realize', self.__realize_cb) self.connect('destroy', self.__destroy_cb, document_path) self.connect('key-press-event', self.__key_press_event_cb) self._vbox = Gtk.VBox() self.add(self._vbox) self._vbox.show() toolbar = Toolbar(title, bundle_path, document_path, sugar_toolkit_path) self._vbox.pack_start(toolbar, False, True, 0) toolbar.connect('stop-clicked', self.__stop_clicked_cb) toolbar.connect('source-selected', self.__source_selected_cb) toolbar.show() pane = Gtk.HPaned() self._vbox.pack_start(pane, True, True, 0) pane.show() self._selected_bundle_file = None self._selected_sugar_file = None file_name = '' activity_bundle = get_bundle_instance(bundle_path) command = activity_bundle.get_command() if _is_web_activity(bundle_path): file_name = 'index.html' elif len(command.split(' ')) > 1: name = command.split(' ')[1].split('.')[-1] tmppath = command.split(' ')[1].replace('.', '/') file_name = tmppath[0:-(len(name) + 1)] + '.py' if file_name: path = os.path.join(bundle_path, file_name) if os.path.exists(path): self._selected_bundle_file = path # Split the tree pane into two vertical panes, one of which # will be hidden tree_panes = Gtk.VPaned() tree_panes.show() self._bundle_source_viewer = FileViewer(bundle_path, file_name) self._bundle_source_viewer.connect('file-selected', self.__file_selected_cb) tree_panes.add1(self._bundle_source_viewer) self._bundle_source_viewer.show() self._sugar_source_viewer = None if sugar_toolkit_path is not None: if _is_web_activity(bundle_path): file_name = 'env.js' else: file_name = 'env.py' self._selected_sugar_file = os.path.join(sugar_toolkit_path, file_name) self._sugar_source_viewer = FileViewer(sugar_toolkit_path, file_name) self._sugar_source_viewer.connect('file-selected', self.__file_selected_cb) tree_panes.add2(self._sugar_source_viewer) self._sugar_source_viewer.hide() pane.add1(tree_panes) self._source_display = SourceDisplay() pane.add2(self._source_display) self._source_display.show() self._source_display.file_path = self._selected_bundle_file if document_path is not None: self._select_source(document_path)
def _is_web_activity(bundle_path): activity_bundle = get_bundle_instance(bundle_path) return activity_bundle.get_command() == 'sugar-activity-web'
def __init__(self, title, bundle_path, document_path, sugar_toolkit_path): Gtk.Toolbar.__init__(self) document_button = None self.bundle_path = bundle_path self.sugar_toolkit_path = sugar_toolkit_path self._add_separator() activity_bundle = get_bundle_instance(bundle_path) file_name = activity_bundle.get_icon() if document_path is not None and os.path.exists(document_path): document_button = DocumentButton(file_name, document_path, title) document_button.connect('toggled', self.__button_toggled_cb, document_path) self.insert(document_button, -1) document_button.show() self._add_separator() if bundle_path is not None and os.path.exists(bundle_path): activity_button = DocumentButton(file_name, bundle_path, title, bundle=True) icon = Icon(file=file_name, pixel_size=style.STANDARD_ICON_SIZE, fill_color=style.COLOR_TRANSPARENT.get_svg(), stroke_color=style.COLOR_WHITE.get_svg()) activity_button.set_icon_widget(icon) icon.show() if document_button is not None: activity_button.props.group = document_button activity_button.props.tooltip = _('Activity Bundle Source') activity_button.connect('toggled', self.__button_toggled_cb, bundle_path) self.insert(activity_button, -1) activity_button.show() self._add_separator() if sugar_toolkit_path is not None: sugar_button = RadioToolButton() icon = Icon(icon_name='computer-xo', pixel_size=style.STANDARD_ICON_SIZE, fill_color=style.COLOR_TRANSPARENT.get_svg(), stroke_color=style.COLOR_WHITE.get_svg()) sugar_button.set_icon_widget(icon) icon.show() if document_button is not None: sugar_button.props.group = document_button else: sugar_button.props.group = activity_button sugar_button.props.tooltip = _('Sugar Toolkit Source') sugar_button.connect('toggled', self.__button_toggled_cb, sugar_toolkit_path) self.insert(sugar_button, -1) sugar_button.show() self._add_separator() self.activity_title_text = _('View source: %s') % title self.sugar_toolkit_title_text = _('View source: %r') % 'Sugar Toolkit' self.label = Gtk.Label() self.label.set_markup('<b>%s</b>' % self.activity_title_text) self.label.set_ellipsize(style.ELLIPSIZE_MODE_DEFAULT) self.label.set_alignment(0, 0.5) self._add_widget(self.label, expand=True) self._add_separator(False) stop = ToolButton(icon_name='dialog-cancel') stop.set_tooltip(_('Close')) stop.connect('clicked', self.__stop_clicked_cb) self.insert(stop, -1) stop.show()
def __init__(self, window_xid, bundle_path, document_path, sugar_toolkit_path, title): Gtk.Window.__init__(self) _logger.debug('ViewSource paths: %r %r %r', bundle_path, document_path, sugar_toolkit_path) self.set_decorated(False) self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.set_border_width(style.LINE_WIDTH) self.set_has_resize_grip(False) width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2 height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2 self.set_size_request(width, height) self._parent_window_xid = window_xid self._sugar_toolkit_path = sugar_toolkit_path self.connect('realize', self.__realize_cb) self.connect('destroy', self.__destroy_cb, document_path) self.connect('key-press-event', self.__key_press_event_cb) vbox = Gtk.VBox() self.add(vbox) vbox.show() toolbar = Toolbar(title, bundle_path, document_path, sugar_toolkit_path) vbox.pack_start(toolbar, False, True, 0) toolbar.connect('stop-clicked', self.__stop_clicked_cb) toolbar.connect('source-selected', self.__source_selected_cb) toolbar.show() pane = Gtk.HPaned() vbox.pack_start(pane, True, True, 0) pane.show() self._selected_bundle_file = None self._selected_sugar_file = None file_name = '' activity_bundle = get_bundle_instance(bundle_path) command = activity_bundle.get_command() if _is_web_activity(bundle_path): file_name = 'index.html' elif len(command.split(' ')) > 1: name = command.split(' ')[1].split('.')[-1] tmppath = command.split(' ')[1].replace('.', '/') file_name = tmppath[0:-(len(name) + 1)] + '.py' if file_name: path = os.path.join(bundle_path, file_name) if os.path.exists(path): self._selected_bundle_file = path # Split the tree pane into two vertical panes, one of which # will be hidden tree_panes = Gtk.VPaned() tree_panes.show() self._bundle_source_viewer = FileViewer(bundle_path, file_name) self._bundle_source_viewer.connect('file-selected', self.__file_selected_cb) tree_panes.add1(self._bundle_source_viewer) self._bundle_source_viewer.show() self._sugar_source_viewer = None if sugar_toolkit_path is not None: if _is_web_activity(bundle_path): file_name = 'env.js' else: file_name = 'env.py' self._selected_sugar_file = os.path.join(sugar_toolkit_path, file_name) self._sugar_source_viewer = FileViewer(sugar_toolkit_path, file_name) self._sugar_source_viewer.connect('file-selected', self.__file_selected_cb) tree_panes.add2(self._sugar_source_viewer) self._sugar_source_viewer.hide() pane.add1(tree_panes) self._source_display = SourceDisplay() pane.add2(self._source_display) self._source_display.show() self._source_display.file_path = self._selected_bundle_file if document_path is not None: self._select_source(document_path)
def __init__(self, handle, create_jobject=True): ''' Initialise the Activity Args: handle (sugar3.activity.activityhandle.ActivityHandle) instance providing the activity id and access to the presence service which *may* provide sharing for this application create_jobject (boolean) DEPRECATED: define if it should create a journal object if we are not resuming. The parameter is ignored, and always will be created a object in the Journal. Side effects: Sets the gdk screen DPI setting (resolution) to the Sugar screen resolution. Connects our "destroy" message to our _destroy_cb method. Creates a base Gtk.Window within this window. Creates an ActivityService (self._bus) servicing this application. Usage: If your Activity implements __init__(), it should call the base class __init()__ before doing Activity specific things. ''' # Stuff that needs to be done early icons_path = os.path.join(get_bundle_path(), 'icons') Gtk.IconTheme.get_default().append_search_path(icons_path) sugar_theme = 'sugar-72' if 'SUGAR_SCALING' in os.environ: if os.environ['SUGAR_SCALING'] == '100': sugar_theme = 'sugar-100' # This code can be removed when we grow an xsettings daemon (the GTK+ # init routines will then automatically figure out the font settings) settings = Gtk.Settings.get_default() settings.set_property('gtk-theme-name', sugar_theme) settings.set_property('gtk-icon-theme-name', 'sugar') settings.set_property('gtk-button-images', True) settings.set_property('gtk-font-name', '%s %f' % (style.FONT_FACE, style.FONT_SIZE)) Window.__init__(self) if 'SUGAR_ACTIVITY_ROOT' in os.environ: # If this activity runs inside Sugar, we want it to take all the # screen. Would be better if it was the shell to do this, but we # haven't found yet a good way to do it there. See #1263. self.connect('window-state-event', self.__window_state_event_cb) screen = Gdk.Screen.get_default() screen.connect('size-changed', self.__screen_size_changed_cb) self._adapt_window_to_screen() # process titles will only show 15 characters # but they get truncated anyway so if more characters # are supported in the future we will get a better view # of the processes proc_title = '%s <%s>' % (get_bundle_name(), handle.activity_id) util.set_proc_title(proc_title) self.connect('realize', self.__realize_cb) self.connect('delete-event', self.__delete_event_cb) self._active = False self._active_time = None self._spent_time = 0 self._activity_id = handle.activity_id self.shared_activity = None self._join_id = None self._updating_jobject = False self._closing = False self._quit_requested = False self._deleting = False self._max_participants = None self._invites_queue = [] self._jobject = None self._read_file_called = False self._session = _get_session() self._session.register(self) self._session.connect('quit-requested', self.__session_quit_requested_cb) self._session.connect('quit', self.__session_quit_cb) accel_group = Gtk.AccelGroup() self.sugar_accel_group = accel_group self.add_accel_group(accel_group) self._bus = ActivityService(self) self._owns_file = False share_scope = SCOPE_PRIVATE if handle.object_id: self._jobject = datastore.get(handle.object_id) if 'share-scope' in self._jobject.metadata: share_scope = self._jobject.metadata['share-scope'] if 'launch-times' in self._jobject.metadata: self._jobject.metadata['launch-times'] += ', %d' % \ int(time.time()) else: self._jobject.metadata['launch-times'] = \ str(int(time.time())) if 'spent-times' in self._jobject.metadata: self._jobject.metadata['spent-times'] += ', 0' else: self._jobject.metadata['spent-times'] = '0' self.shared_activity = None self._join_id = None if handle.object_id is None: logging.debug('Creating a jobject.') self._jobject = self._initialize_journal_object() if handle.invited: wait_loop = GObject.MainLoop() self._client_handler = _ClientHandler( self.get_bundle_id(), partial(self.__got_channel_cb, wait_loop)) # FIXME: The current API requires that self.shared_activity is set # before exiting from __init__, so we wait until we have got the # shared activity. http://bugs.sugarlabs.org/ticket/2168 wait_loop.run() else: pservice = presenceservice.get_instance() mesh_instance = pservice.get_activity(self._activity_id, warn_if_none=False) self._set_up_sharing(mesh_instance, share_scope) if self.shared_activity is not None: self._jobject.metadata['title'] = self.shared_activity.props.name self._jobject.metadata['icon-color'] = \ self.shared_activity.props.color else: self._jobject.metadata.connect('updated', self.__jobject_updated_cb) self.set_title(self._jobject.metadata['title']) bundle = get_bundle_instance(get_bundle_path()) self.set_icon_from_file(bundle.get_icon())